package com.twq.collection.framework.map

import java.util.concurrent.TimeUnit

/**
 * Created by tangweiqun on 2017/11/16.
 */
object MapTest {
  def main(args: Array[String]): Unit = {
    //1、在scala.Predef中定义了一个隐式转换，把A -> B 的表达式转换为元组(A, B)
    val errorCodes = Map(1 -> "NOES", 2 -> "KTHXBAI", 3 -> "ZOMG")

    //2、Map能用作从键类型到值类型的偏函数
    val result = List(1, 3) map errorCodes //result: List[String] = List(NOES, ZOMG)

    //3、Map还提供了当键不存在时返回默认值的能力
    val addresses = Map("katy" -> "someplace 123").withDefaultValue("default place")
    addresses("john") //default place

    //4、在scala社区中一般习惯直接用通用的Map类型

    //所有的方法：
    val ms = Map("x" -> 24, "y" -> 25, "z" -> 26) //默认类型是scala.collection.immutable.Map
    //Lookups
    ms.get("x")
    ms("x")
    ms.getOrElse("c", 33)
    ms.contains("c")
    ms.isDefinedAt("d") //Same as contains

    //Additions and Updates
    ms + ("c" -> 33)
    ms + ("c" -> 33, "d" -> 34)
    ms ++ Map("f" -> 32, "h" -> 88)
    ms.updated("x", 23) //效果和ms + (k -> v)一样

    //Removals
    ms - "c"
    ms - ("x", "y", "d")
    ms -- (Seq("c", "d"))

    //Subcollections
    ms.keys
    ms.keySet
    ms.keysIterator
    ms.values
    ms.valuesIterator

    //Transformation
    ms.filterKeys(_.contains("c"))
    ms.mapValues(_ + 4)

    //可变的Map的方法：
    val mutableMap = scala.collection.mutable.Map("x" -> 24, "y" -> 25, "z" -> 26) // scala.collection.mutable.Map
    //Additions and Updates
    mutableMap("x") = 99
    mutableMap += ("c" -> 98)
    mutableMap += ("d" -> 98, "m" -> 77)
    mutableMap ++= Map("l" -> 2)
    mutableMap.put("v", 23)
    mutableMap.getOrElseUpdate("l", 8)
    //可以用于缓存，如下：
    val cache = collection.mutable.Map[String, String]()

    def cachedF(s: String) = cache.getOrElseUpdate(s, f(s)) //第二个参数是by-name参数，用的时候才会取计算
    cachedF("abd")
    cachedF("abd")

    def cachedF_1(arg: String) = cache get arg match {
      case Some(result) => result
      case None =>
        val result = f(arg)
        cache(arg) = result
        result
    }

    //Removals
    mutableMap -= "c"
    mutableMap -= ("x", "y", "d")
    mutableMap --= (Seq("c", "d"))
    mutableMap.remove("v")
    mutableMap.retain((key, value) => key != "d")
    mutableMap.clear()

    //Transformation
    mutableMap.transform((key, value) => value + 23)

    //Cloning
    mutableMap.clone()
  }

  def f(x: String) = {
    println("taking my time.");
    TimeUnit.SECONDS.sleep(2)
    x.reverse
  }
}
